package game;

import javax.swing.*;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.awt.event.*;
import java.io.FileNotFoundException;
import java.util.ArrayList;
public class GameUI{
	InputGame iGame;
	int gameSize;
	static GameFrame frame;
	String filename;
	JFrame gf;
	GameLayeredPane glp;
	

	ArrayList<Cell> cells;

	final String help = "How to play:" + '\n' + "1.Select a game in 'Start';"
			+ '\n' + "2.Read the game;" + "\n"
			+ "3.Enter your answer;" + '\n' + "4.Click 'Check';" + '\n'
			+ "5.Get your result."+"\n\n"+"* You could click right mouse on each cell"+'\n'+"to call the popup menu and make a note";
	int gameInputed = 0;

	static final Font textFont = new Font("SansSerif", Font.BOLD, 50);
	static final Font noteFont = new Font("Serif", Font.ITALIC|Font.BOLD, 15);

	

	public GameUI() {
		gameSize = 4;
		
		cells = new ArrayList<Cell>(gameSize*gameSize);
		for(int i=0;i<gameSize*gameSize;i++){
		cells.add(new Cell(gameSize));
		}
		
		frame = new GameFrame(gameSize);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		glp = new GameLayeredPane(gameSize);

		glp.setOpaque(true);
		frame.add(glp,BorderLayout.CENTER);
		
		frame.setVisible(true);
	}

	public static void main(String args[]) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				GameUI g = new GameUI();
			}
		});

	}
	


	public void setCageBorder() {
		int numOfCages = this.iGame.getGame().mCages.size();

		for(int i=0;i<numOfCages;i++){
			int pos = this.iGame.getGame().mCages.get(i).mCells.get(0).mRow*this.gameSize+this.iGame.getGame().mCages.get(i).mCells.get(0).mColumn;
			this.glp.labelPanel.labels.get(pos).setText(this.iGame.getGame().mCages.get(i).mText);
			
			int numOfCellsInCage = this.iGame.getGame().mCages.get(i).mCells.size();
			switch(numOfCellsInCage){
			case 1:
				this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,2,2,Color.black));
				break;
			case 2:
				if(this.iGame.getGame().mCages.get(i).mCells.get(0).mRow==this.iGame.getGame().mCages.get(i).mCells.get(1).mRow){
					this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,2,0,Color.black));
					this.glp.textPanel.textCells.get(pos+1).setBorder(new MatteBorder(2,0,2,2,Color.black));
				}else
				{
					this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,0,2,Color.black));
					this.glp.textPanel.textCells.get(pos+this.gameSize).setBorder(new MatteBorder(0,2,2,2,Color.black));
				}
				break;
			case 3:
				if(this.iGame.getGame().mCages.get(i).mCells.get(0).mRow==this.iGame.getGame().mCages.get(i).mCells.get(1).mRow){
					if(this.iGame.getGame().mCages.get(i).mCells.get(1).mRow==this.iGame.getGame().mCages.get(i).mCells.get(2).mRow){	
						this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,2,0,Color.black));
						this.glp.textPanel.textCells.get(pos+1).setBorder(new MatteBorder(2,0,2,0,Color.black));
						this.glp.textPanel.textCells.get(pos+2).setBorder(new MatteBorder(2,0,2,2,Color.black));
					}
					else if(this.iGame.getGame().mCages.get(i).mCells.get(0).mColumn==this.iGame.getGame().mCages.get(i).mCells.get(2).mColumn){
						this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,0,0,Color.black));
						this.glp.textPanel.textCells.get(pos+1).setBorder(new MatteBorder(2,0,2,2,Color.black));
						this.glp.textPanel.textCells.get(pos+this.gameSize).setBorder(new MatteBorder(0,2,2,2,Color.black));
					}
					else{
						this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,2,0,Color.black));
						this.glp.textPanel.textCells.get(pos+1).setBorder(new MatteBorder(2,0,0,2,Color.black));
						this.glp.textPanel.textCells.get(pos+1+this.gameSize).setBorder(new MatteBorder(0,2,2,2,Color.black));
						
					}
					
				}
				else if(this.iGame.getGame().mCages.get(i).mCells.get(0).mColumn==this.iGame.getGame().mCages.get(i).mCells.get(1).mColumn){
					if(this.iGame.getGame().mCages.get(i).mCells.get(1).mColumn==this.iGame.getGame().mCages.get(i).mCells.get(2).mColumn){
						this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,0,2,Color.black));
						this.glp.textPanel.textCells.get(pos+this.gameSize).setBorder(new MatteBorder(0,2,0,2,Color.black));
						this.glp.textPanel.textCells.get(pos+this.gameSize*2).setBorder(new MatteBorder(0,2,2,2,Color.black));
					}
					else if(this.iGame.getGame().mCages.get(i).mCells.get(1).mRow<this.iGame.getGame().mCages.get(i).mCells.get(2).mRow){
						this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,0,2,Color.black));
						this.glp.textPanel.textCells.get(pos+this.gameSize).setBorder(new MatteBorder(0,2,2,0,Color.black));
						this.glp.textPanel.textCells.get(pos+this.gameSize+1).setBorder(new MatteBorder(2,0,2,2,Color.black));
					}
					else{
						this.glp.textPanel.textCells.get(pos).setBorder(new MatteBorder(2,2,0,2,Color.black));
						this.glp.textPanel.textCells.get(pos+this.gameSize).setBorder(new MatteBorder(0,0,2,2,Color.black));
						this.glp.textPanel.textCells.get(pos+this.gameSize-1).setBorder(new MatteBorder(2,2,2,0,Color.black));
					}
				}

			}
		}
		

	}


	class ButtonPanel extends JPanel {
		ArrayList<JButton> buttons;
		public ButtonPanel(int size) {
			this.setLayout(new FlowLayout());
			this.buttons = new  ArrayList<JButton>();
			for (int i = 0; i < size; i++) {
				buttons.add(new JButton(Character.toString((char) ('1' + i))));
				this.add(buttons.get(i));
			}

			this.add(new JButton("-"));
		}
	}

	
	class NotePanel extends JPanel{
		ArrayList<JLabel> notes;
		public NotePanel(int size) {
			notes =new ArrayList<JLabel>(size*size);
			setLayout(new GridLayout(size, size,1,1));
			for (int i = 0; i < size * size; i++) {
				notes.add(cells.get(i).label);
				notes.get(i).setOpaque(false);
				notes.get(i).setFont(noteFont);
				notes.get(i).setForeground(Color.BLUE);
				notes.get(i).setVerticalAlignment(JLabel.BOTTOM);
				notes.get(i).setHorizontalAlignment(JLabel.RIGHT);
				add(notes.get(i));
			}
			setBounds(2, 2, 450, 450);
			

			setOpaque(false);
			
		}

		public NotePanel() {

		}
	}
	
	class Cell{
		PopupMenu pm;	
		String note;
		JTextField text;
		JLabel label;
		int[] flags;
		
		
		class PopupMenu{
			JPopupMenu noteMenu;
			ArrayList<JCheckBoxMenuItem> notes;
			JMenuItem clear;
			MouseListener popupListener;
			
			PopupMenu(int size){
				noteMenu = new JPopupMenu();
				notes = new ArrayList<JCheckBoxMenuItem>();

				// Create the menu.
				for (int j = 0; j < size; j++) {
					notes.add(new JCheckBoxMenuItem(Character
							.toString((char) ('1' + j))));
					notes.get(j).addItemListener(new CheckListener());
					noteMenu.add(notes.get(j));
				}
				clear = new JMenuItem("Clear");
				clear.addActionListener(new NoteListener());
				noteMenu.add(clear);
				
				popupListener = new PopupListener(noteMenu);
			}
		
			
			class NoteListener implements ActionListener{


				public void actionPerformed(ActionEvent e) {
					JMenuItem source = (JMenuItem)(e.getSource());
					if(source.getText() =="Clear"){
						note = "";
						label.setText("");
						for(int i=0;i<pm.notes.size();i++){
							pm.notes.get(i).setState(false);
						}
						
					}
				}
				
				public void itemStateChanged(ItemEvent e) {
			        JMenuItem source = (JMenuItem)(e.getSource());
			     
			        label.setText("fsdf");
			    }
			}
			
			class CheckListener implements ItemListener{

				@Override
				public void itemStateChanged(ItemEvent e) {
					note = "";
				     JMenuItem source = (JMenuItem)(e.getSource());					
				     flags[Integer.parseInt(source.getText())-1] *= -1;
				     for(int i=0;i<flags.length;i++){
				    	 if(flags[i] == 1){
							note = note + (i+1) + " ";
				    	 }
				     }
				     label.setText(note);
					
				}
				
			}
		}
		
		Cell(int size){
			text = new JTextField();
			pm = new PopupMenu(size);
			label = new JLabel();
			flags = new int[size];
			for(int i = 0;i<size;i++){
				flags[i] = -1;
			}
			note = " ";
			text.addMouseListener(pm.popupListener);
			
			
			
		}
		
			
				
		
		
	}
	

	class TextPanel extends JPanel {
		ArrayList<JTextField> textCells;


		public TextPanel(int size) {

			setLayout(new GridLayout(size, size,1,1));

			this.textCells = new ArrayList<JTextField>(size * size);
			for (int i = 0; i < size * size; i++){
				final JTextField t = cells.get(i).text;
				t.setOpaque(true);
				t.setFont(textFont);
				t.setHorizontalAlignment(JTextField.CENTER);
				t.addKeyListener(new KeyListener() {

					@Override
					public void keyTyped(KeyEvent e) {
						char ch = e.getKeyChar();
						if (Character.isDigit(ch) && ch > '0'
								&& ch <= '0' + gameSize) {
							t.setText("");

						} else {
							e.consume();
						}

					}

					@Override
					public void keyPressed(KeyEvent e) {
						// TODO Auto-generated method stub

					}

					@Override
					public void keyReleased(KeyEvent e) {
						// TODO Auto-generated method stub

					}

				});
		
				

				
				this.textCells.add(t);
				
				add(this.textCells.get(i));
				
				
				
			}
			setBounds(3,3, 450, 450);	
			setOpaque(true);

		}

		public TextPanel() {

		}
	}
	class PopupListener extends MouseAdapter {
        JPopupMenu popup;
 
        PopupListener(JPopupMenu popupMenu) {
            popup = popupMenu;
        }
 
        public void mousePressed(MouseEvent e) {
            maybeShowPopup(e);
        }
 
        public void mouseReleased(MouseEvent e) {
            maybeShowPopup(e);
        }
 
        private void maybeShowPopup(MouseEvent e) {
            if (e.isPopupTrigger()) {
                popup.show(e.getComponent(),
                           e.getX(), e.getY());
            }
        }
    }

	class LabelPanel extends JPanel {
		ArrayList<JLabel> labels;
		public LabelPanel(int size) {
			labels =new ArrayList<JLabel>(size*size);
			setLayout(new GridLayout(size, size,1,1));
			for (int i = 0; i < size * size; i++) {
				labels.add(new JLabel());
				labels.get(i).setOpaque(false);
				labels.get(i).setVerticalAlignment(JLabel.TOP);
				labels.get(i).setHorizontalAlignment(JLabel.LEFT);
				add(labels.get(i));
			}
			setBounds(2, 2, 450, 450);
			

			setOpaque(false);
			
		}

		public LabelPanel() {

		}
	}
	
	


	class GameLayeredPane extends JLayeredPane {
		TextPanel textPanel;
		LabelPanel labelPanel;
		NotePanel notePanel;
	//	ArrayList<NoteMenu> noteMenu;
		
		
		public GameLayeredPane(int size) {

			textPanel = new TextPanel(size);
			labelPanel = new LabelPanel(size);
			notePanel = new NotePanel(size);
	
			
			add(notePanel,new Integer(2));
			add(labelPanel, new Integer(1));
			add(textPanel, new Integer(0));
			




		}
	}

	class GameFrame extends JFrame {
		public static final int DEFAULT_WIDTH = 470;
		public static final int DEFAULT_HIGHT = 520;
		JMenuBar jmb;

		int size;

		public GameFrame(int size) {

			this.size = size;
			jmb = new JMenuBar();
			JMenu start = new JMenu("Start");
			JMenuItem check = new JMenuItem("Check");
			JMenuItem game1 = new JMenuItem("Game 1");
			JMenuItem game2 = new JMenuItem("Game 2");
			JMenuItem game3 = new JMenuItem("Game 3");
			JMenuItem mhelp = new JMenuItem("Help");

			game1.addActionListener(new StartAction("Game1.txt"));
			game2.addActionListener(new StartAction("Game2.txt"));
			game3.addActionListener(new StartAction("Game3.txt"));

			check.addActionListener(new CheckAction());
			mhelp.addActionListener(new HelpAction());

			setTitle("KenkenGame");
			setSize(DEFAULT_WIDTH, DEFAULT_HIGHT);
			setJMenuBar(jmb);

			start.add(game1);
			start.add(game2);
			start.add(game3);

			jmb.add(start);
			jmb.add(check);
			jmb.add(mhelp);

		}
	}

	class StartAction implements ActionListener {
		private String filename;

		public StartAction(String s) {
			filename = s;
		}

		public void actionPerformed(ActionEvent e) {
			try {
				generate(filename);

			} catch (Exception e1) {
				e1.printStackTrace();
			}

		}

	}

	class CheckAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (gameInputed == 0) {
				JOptionPane.showMessageDialog(null, "Start a game first!",
						"No game", JOptionPane.INFORMATION_MESSAGE);
			} else if (!checkAnswer()) {
				JOptionPane.showMessageDialog(null, "Wrong answer!", "Wrong",
						JOptionPane.INFORMATION_MESSAGE);
			} else {
				JOptionPane.showMessageDialog(null, "YOU SOLVED THIS PUZZLE!",
						"Congratulation!", JOptionPane.INFORMATION_MESSAGE);
			}

		}
	}

	class HelpAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			JOptionPane.showMessageDialog(frame, help, "Help",
					JOptionPane.OK_OPTION);

		}
	}

	public void generate(String filename) throws FileNotFoundException {
		iGame = new InputGame(filename);
		System.out.println(iGame.gameDesc);

		gameSize = this.iGame.getGame().mGridSize;
		frame.remove(glp);
		
		cells = new ArrayList<Cell>(gameSize*gameSize);
		for(int i=0;i<gameSize*gameSize;i++){
		cells.add(new Cell(gameSize));
		}


		glp = new GameLayeredPane(iGame.getGame().mGridSize);

		this.setCageBorder();

		frame.add(glp, BorderLayout.CENTER);
		frame.validate();
		frame.setVisible(true);
		this.gameInputed = 1;

	}

	public boolean checkAnswer() {

		int[][] answer = new int[gameSize][gameSize];

		for (int i = 0; i < gameSize; i++) {
			for (int j = 0; j < gameSize; j++) {
				String str = this.glp.textPanel.textCells.get(i * gameSize + j)
						.getText();
				if (str.length() != 1 || Integer.parseInt(str) > gameSize
						|| Integer.parseInt(str) < 0) {
					return false;
				} else {
					answer[i][j] = Integer.parseInt(str);
				}
			}
		}

		if (!this.iGame.getGame().checkAnswer(answer)) {
			return false;
		}

		return true;
	}
		


}


